﻿using DryIoc;
using PLCSharp.CoreModel.Common;
using PLCSharp.CoreModel.Prism;
using Prism.Commands;
using Prism.Dialogs;
using Prism.Ioc;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Threading;

namespace PLCSharp.Views.Connects.Socket
{

    public class SocketClientConfigViewModel : ValidateBase, IDialogAware
    {
        public SocketClientConfigViewModel(IContainerExtension container)
        {
            _ConnectsModel = container.Resolve<ConnectsModel>();
            bkgWorker = new BackgroundWorker { WorkerSupportsCancellation = true };
            bkgWorker.DoWork += BackgroundWork;

            if (!bkgWorker.IsBusy)
                bkgWorker.RunWorkerAsync();
        }

        private readonly ConnectsModel _ConnectsModel;
        private string _Title = "Socket Client";

        public string Title
        {
            get { return _Title; }
            set
            {
                SetProperty(ref _Title, value);
            }
        }
        public DialogCloseListener RequestClose { get; }

        public bool CanCloseDialog()
        {
            return true;
        }
        public void OnDialogClosed()
        {
            Client.LogSwitch = false;
            bkgWorker.CancelAsync();
            bkgWorker.Dispose();
        }

        public void OnDialogOpened(IDialogParameters parameters)
        {
            var name = parameters.GetValue<string>("Name");

            Client = _ConnectsModel.Connects.Where(c => c.Name == name).FirstOrDefault();

            IP = Client.IP;
            Port = Client.Port;
            Client.LogSwitch = true;


        }

        private readonly BackgroundWorker bkgWorker;

        private void BackgroundWork(object sender, DoWorkEventArgs e)
        {
            var worker = (BackgroundWorker)sender;

            while (!worker.CancellationPending)
            {
                Thread.Sleep(10);
                if (Client != null)
                {

                    if (Client.LogSwitch)
                    {
                        if (!(Client as SocketClient).LogQueue.IsEmpty)
                        {
                            if ((Client as SocketClient).LogQueue.TryDequeue(out string log))

                                System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                                {
                                    Logs.Add(new(log));
                                }));
                        }
                    }
                }

            }
        }




        private Connect _Client;
        /// <summary>
        /// Comment
        /// </summary>
        public Connect Client
        {
            get { return _Client; }
            set { SetProperty(ref _Client, value); }
        }
        //日志
        private ObservableCollection<ErrorLog> _Logs = [];

        public ObservableCollection<ErrorLog> Logs
        {
            get { return _Logs; }
            set { SetProperty(ref _Logs, value); }
        }

        // IP
        private string _IP = "127.0.0.1";

        [Required(ErrorMessage = "IP不能为空！")]
        [RegularExpression(@"^([1-9]\d?|1\d{2}|2[01]\d|22[0-3])(\.([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])){3}$", ErrorMessage = "IP地址格式不正确")]
        public string IP
        {
            get { return _IP; }
            set
            {
                SetProperty(ref _IP, value);
                Client.IP = value;
            }
        }

        // PORT
        private int _Port = 7950;

        [Required(ErrorMessage = "端口不能为空！")]
        [Range(0, 65535, ErrorMessage = "端口应在0-65535之间.")]
        public int Port
        {
            get { return _Port; }
            set
            {
                SetProperty(ref _Port, value);

                Client.Port = value;
            }
        }


        private string _SendString = "hello";

        public string SendString
        {
            get { return _SendString; }
            set
            {
                SetProperty(ref _SendString, value);
            }
        }

        #region Command

        private AsyncDelegateCommand _Send;

        public AsyncDelegateCommand Send =>
            _Send ??= new AsyncDelegateCommand(ExecuteSendAsync);


        private async Task ExecuteSendAsync()

        {
            await Client.SendAsync(SendString);

        }



        #endregion Command
    }
}